package service

import (
	"encoding/json"
	"fmt"
	"mumu_stock_trad/util"
	"strings"
	"sync"
	"time"

	log "github.com/sirupsen/logrus"
)

const (
	ACEKEY = "DJS2giHB3NzyAad5UbN7YQ=="
)

// StockData 表示股票交易的数据结构
type StockData struct {
	// 股票代码，通常是由字母和数字组成的字符串，例如 "AAPL" 或 "000001"
	Code string `json:"code"` // 代码

	// 股票价格，表示交易时的价格
	// 例如：当买入/卖出时，股票的市场价格
	Price float64 `json:"price,omitempty"` // 价格

	// 卖出数量，表示在卖出操作中计划卖出的股票数量
	// 例如：你想卖出 100 股股票，那么该值就为 100
	SellCount int `json:"sellCount,omitempty"` // 卖出数量

	// 卖出百分比，表示相对于某个基准（例如当前持股数量）卖出的百分比
	// 例如：卖出 50% 的持股，卖出百分比为 50
	SellPercent int `json:"sellPercent,omitempty"` // 卖出百分比

	// 时间，表示交易的时间，通常格式为 "YYYY-MM-DD HH:MM:SS"
	// 例如：交易发生在 "2023-10-10 14:30:00"
	Time string `json:"time"` // 时间

	// 类型，表示交易的类型。类型定义如下：
	// 0:  打板买入
	// 1:  打板卖出
	// 2:  反核买入
	// 3:  盘中反核买入
	// 4:  撤买单
	// 5:  撤卖单
	// 11: 卖出全部
	Type int `json:"type"` // 类型
}

// 让我们暴富起来
func GoRich() {
	log.Info("机器人跑起来~")

	time.Sleep(time.Second * 5)

	// 随机操作
	go func() {
		for {
			buySellDTO := BuySellDTO{
				Type: 3,
			}
			handle(buySellDTO)
			time.Sleep(time.Minute * 30)
		}
	}()

	// // 模拟买入
	go func() {
		for {
			buySellDTO := BuySellDTO{
				Type:    1,
				StockNo: "601933",
				Price:   6.55,
				Count:   100,
			}
			handle(buySellDTO)
			time.Sleep(time.Second * 10)
		}
	}()
}

// 获取交易信息
func GetTrad() (string, error) {
	// 设置目标 URL
	url := "http://14.103.238.132:10000/newServer/s/real/doOutPost"

	// 准备 POST 数据（根据 API 需要格式调整）
	postData := []byte(`12`)

	// 设置请求头（可以根据需要设置不同的请求头）
	headers := map[string]string{
		"Content-Type": "application/json",
	}

	// 调用通用 POST 请求函数
	status, body, err := util.PostRequestRaw(url, postData, headers)
	if err != nil {
		// log.Fatalf("Error sending POST request: %v", err)
		log.Error("Error sending POST request: ", err.Error())
		return "", nil
	}

	// 打印响应内容
	fmt.Println("Response Status:", status)
	fmt.Println("Response Body:", body)

	return body, nil
}

// 交易类型对应的描述
var typeDescriptions = map[int]string{
	0:  "打板买入",
	1:  "打板卖出",
	2:  "反核买入",
	3:  "盘中反核",
	4:  "撤撤买单",
	5:  "撤撤卖单",
	11: "卖出全部",
}

// formatStockData 将一笔交易转成明文字符串
func formatStockData(data StockData) string {
	desc, ok := typeDescriptions[data.Type]
	if !ok {
		desc = fmt.Sprintf("未知类型(%d)", data.Type)
	}

	// 使用格式化来确保输出结果整齐
	return fmt.Sprintf("%-5s 股票:%-6s 价格:%4.2f  股数:%4d --- %3d%% %s",
		desc, data.Code, data.Price, data.SellCount, data.SellPercent, data.Time)
}

// 用于记录已发送邮件的哈希，做幂等控制
var (
	sentEmails = make(map[string]struct{})
	emailLock  sync.Mutex
)

func MockEmail(mock []StockData) {

	// 创建一个字符串切片，用于存放每一笔交易的信息
	var result []string
	for _, trade := range mock {
		result = append(result, formatStockData(trade))
	}

	// 将所有交易信息用换行符拼接起来
	finalResult := strings.Join(result, "\n")

	// 输出拼接后的结果
	fmt.Println(finalResult)

	// 发件人信息
	from := "1195154798@qq.com"    // 发件人邮箱
	password := "ucvmubxwdtqoiedd" // QQ邮箱授权码（不是密码）

	// 收件人信息，可以同时发送给多个收件人
	to := []string{
		"913546238@qq.com",
		// "350206327@qq.com",
	}

	// 邮件主题和正文
	// subject := "交易推送"
	// body := finalResult

	// // 调用通用发送邮件方法
	// if err := util.SendEmail(from, password, to, subject, body); err != nil {
	// 	log.Fatal("邮件发送失败:", err)
	// } else {
	// 	log.Println("邮件发送成功")
	// }

	for _, trade := range mock {
		body := formatStockData(trade)
		hash := util.HashString(body)

		emailLock.Lock()
		if _, sent := sentEmails[hash]; sent {
			emailLock.Unlock()
			continue
		}
		sentEmails[hash] = struct{}{}
		emailLock.Unlock()

		if err := util.SendEmail(from, password, to, body, body); err != nil {
			log.Error("邮件发送失败:", err, body)
			emailLock.Lock()
			delete(sentEmails, hash)
			emailLock.Unlock()
		} else {
			log.Info("邮件发送成功 ", body)
		}
	}

}

// 解密数据
func DecryptTrad(data string) error {
	// 解密
	decryptedData, err := util.Decrypt(data, ACEKEY)
	if err != nil {
		fmt.Println("Error decrypting data:", err)
		return err
	}
	fmt.Println("--------------")
	if decryptedData != "[]" {
		// log.Info("交易信息：", decryptedData)
		var stockData []StockData
		err = json.Unmarshal([]byte(decryptedData), &stockData)
		if err != nil {
			log.Error(err)
			return err
		}

		go MockEmail(stockData)
	}
	fmt.Println("Decrypted data:", decryptedData)
	return nil
}

// 定义第一组操作类型（打板操作）
const (
	BoardBuy         = 0  // 打板买入
	BoardSell        = 1  // 打板卖出
	ReverseBuy       = 2  // 反核买入
	MiddayReverseBuy = 3  // 盘中反核买入
	CancelBuy        = 4  // 撤买单
	CancelSell       = 5  // 撤卖单
	SellAll          = 11 // 卖出全部
)

// 定义第二组操作类型（普通操作）
const (
	Buy         = 0 // 买入
	Sell        = 1 // 卖出
	CancelSell2 = 2 // 撤卖单
	RandomOp    = 3 // 随机操作
	CancelBuy2  = 4 // 撤买单
)

func HandleTrad(data StockData) {
	// 定义第一组到第二组的操作类型映射关系
	operationMap := map[int]int{
		BoardBuy:         Buy,         // 打板买入 -> 买入
		BoardSell:        Sell,        // 打板卖出 -> 卖出
		ReverseBuy:       Buy,         // 反核买入 -> 买入
		MiddayReverseBuy: Buy,         // 盘中反核买入 -> 买入
		CancelBuy:        CancelBuy2,  // 撤买单 -> 撤买单
		CancelSell:       CancelSell2, // 撤卖单 -> 撤卖单
		SellAll:          Sell,        // 卖出全部 -> 卖出
	}

	buySellDTO := BuySellDTO{
		Type:    operationMap[data.Type],
		StockNo: data.Code,
		Price:   data.Price,
		Count:   data.SellCount,
	}

	// if buySellDTO.Type != CancelBuy2 && buySellDTO.Type != CancelSell2 {
	fmt.Println("执行指令：", buySellDTO)
	handle(buySellDTO)
	// }
}
